
package ch.hearc.meteo.imp.afficheur.real.vue.atome;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.rmi.RemoteException;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JToggleButton;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import ch.hearc.meteo.imp.afficheur.real.JFrameStationMeteo;
import ch.hearc.meteo.imp.afficheur.real.moo.StationMeteoElement;
import ch.hearc.meteo.tools.ImageShop;

public class JPanelControl extends JPanel
	{

	/*------------------------------------------------------------------*\
	|*							Constructeurs							*|
	\*------------------------------------------------------------------*/
	public JPanelControl(List<StationMeteoElement> listStationMeteoElements)
		{
		this.listStationMeteoElements = listStationMeteoElements;
		this.lastAltitudeDelay = 0;
		this.lastPressionDelay = 0;
		this.lastTemperatureDelay = 0;
		geometry();
		control();
		apparence();
		runSliderPulling();
		}

	private void runSliderPulling()
		{
		updateTimer = new Timer();
		updateTimer.scheduleAtFixedRate(new TimerTask()
			{

				@Override
				public void run()
					{
					synchronized (JPanelControl.this.listStationMeteoElements)
						{
						int altitudeDelay = 0;
						int pressionDelay = 0;
						int temperatureDelay = 0;

						boolean altitudeDelayDifference = false;
						boolean pressionDelayDifference = false;
						boolean temperatureDelayDifference = false;

						int cmpt = 0;
						for(StationMeteoElement stationMeteoElement:JPanelControl.this.listStationMeteoElements)
							{

							int newAltitudeDelay = 0;
							int newPressionDelay = 0;
							int newTemperatureDelay = 0;
							try
								{

								if (JFrameStationMeteo.getInstance().isLocal() == true)
									{
									newAltitudeDelay = (int)stationMeteoElement.getPcLocal().getAfficheurService().getMeteoServiceOptions().getAltitudeDT();
									newPressionDelay = (int)stationMeteoElement.getPcLocal().getAfficheurService().getMeteoServiceOptions().getPressionDT();
									newTemperatureDelay = (int)stationMeteoElement.getPcLocal().getAfficheurService().getMeteoServiceOptions().getTemperatureDT();
									}
								else
									{
									newAltitudeDelay = (int)stationMeteoElement.getMeteoService().getMeteoServiceOptions().getAltitudeDT();
									newPressionDelay = (int)stationMeteoElement.getMeteoService().getMeteoServiceOptions().getPressionDT();
									newTemperatureDelay = (int)stationMeteoElement.getMeteoService().getMeteoServiceOptions().getTemperatureDT();
									}

								if (cmpt == 0)
									{
									altitudeDelay = newAltitudeDelay;
									pressionDelay = newPressionDelay;
									temperatureDelay = newTemperatureDelay;
									}
								else
									{
									if (newAltitudeDelay != altitudeDelay)
										{
										altitudeDelayDifference = true;
										}
									if (newPressionDelay != pressionDelay)
										{
										pressionDelayDifference = true;
										}
									if (newTemperatureDelay != temperatureDelay)
										{
										temperatureDelayDifference = true;
										}
									}

								}
							catch (RemoteException e)
								{
								e.printStackTrace();
								}

							cmpt++;
							}

						if (altitudeDelay != lastAltitudeDelay)
							{
							//System.out.println("IF : DIFF" + altitudeDelayDifference);
							updateSlider(sliderDelayAltitude, lblDelayAltitude, altitudeDelay, altitudeDelayDifference);
							if (!altitudeDelayDifference)
								{
								lastAltitudeDelay = altitudeDelay;
								}
							}
						else
							{
							//System.out.println("ELSE : DIFF" + altitudeDelayDifference);
							updateSlider(sliderDelayAltitude, lblDelayAltitude, sliderDelayAltitude.getValue(), altitudeDelayDifference);
							}

						if (pressionDelay != lastPressionDelay)
							{
							updateSlider(sliderDelayPression, lblDelayPression, pressionDelay, pressionDelayDifference);
							if (!pressionDelayDifference)
								{
								lastPressionDelay = pressionDelay;
								}

							}
						else
							{
							updateSlider(sliderDelayPression, lblDelayPression, sliderDelayPression.getValue(), pressionDelayDifference);
							}

						if (temperatureDelay != lastTemperatureDelay)
							{
							updateSlider(sliderDelayTemperature, lblDelayTemperature, temperatureDelay, temperatureDelayDifference);
							if (!temperatureDelayDifference)
								{
								lastTemperatureDelay = temperatureDelay;
								}
							}
						else
							{
							updateSlider(sliderDelayTemperature, lblDelayTemperature, sliderDelayTemperature.getValue(), temperatureDelayDifference);
							}

						}
					}
			}, 0, DELAY_PULLING_SLIDER);
		}

	/*------------------------------------------------------------------*\
	|*							Methodes Public							*|
	\*------------------------------------------------------------------*/
	public void refresh()
		{
		boolean enabled = this.listStationMeteoElements.size() > 0;
		this.btnStart.setEnabled(enabled);
		this.btnStop.setEnabled(enabled);
		this.tglBtnPause.setEnabled(enabled);
		this.sliderDelayAltitude.setEnabled(enabled);
		this.sliderDelayPression.setEnabled(enabled);
		this.sliderDelayTemperature.setEnabled(enabled);

		}

	/*------------------------------*\
	|*				Set				*|
	\*------------------------------*/

	/*------------------------------*\
	|*				Get				*|
	\*------------------------------*/

	public boolean isControlEnabled()
		{
		return controlEnabled;
		}

	/*------------------------------------------------------------------*\
	|*							Methodes Private						*|
	\*------------------------------------------------------------------*/

	private void updateSlider(JSlider slider, JLabel label, int value, boolean valueDifference)
		{
		if (!valueDifference)
			{
			slider.setValue(value);
			label.setText(String.valueOf(value));
			label.setForeground(Color.WHITE);
			}
		else
			{
			label.setForeground(Color.RED);
			}
		repaint();
		}

	private void apparence()
		{

		Font font = this.getFont().deriveFont(12);
		Border border = BorderFactory.createTitledBorder(BorderFactory.createLineBorder(JFrameStationMeteo.COLOR_S1, 1, true), "Contrôle", TitledBorder.CENTER, TitledBorder.TOP, font, JFrameStationMeteo.COLOR_BLACK);
		this.setBorder(border);
		}

	private void control()
		{
		this.btnStart.addActionListener(new ActionListener()
			{

				@Override
				public void actionPerformed(ActionEvent event)
					{

					new Thread(new Runnable()
						{

							@Override
							public void run()
								{
								setControlEnabled(false);
								synchronized (listStationMeteoElements)
									{
									for(StationMeteoElement stationMeteoElement:listStationMeteoElements)
										{
										try
											{
											stationMeteoElement.getMeteoService().start(stationMeteoElement.getMeteoServiceOptions());
											}
										catch (RemoteException e)
											{
											e.printStackTrace();
											}
										}
									}
								setControlEnabled(true);
								}
						}).start();

					}
			});
		this.btnStop.addActionListener(new ActionListener()
			{

				@Override
				public void actionPerformed(ActionEvent event)
					{
					new Thread(new Runnable()
						{

							@Override
							public void run()
								{
								setControlEnabled(false);
								synchronized (listStationMeteoElements)
									{
									for(StationMeteoElement stationMeteoElement:listStationMeteoElements)
										{
										try
											{
											stationMeteoElement.getMeteoService().stop();
											}
										catch (RemoteException e)
											{
											e.printStackTrace();
											}
										}
									}
								setControlEnabled(true);
								}
						}).start();

					}
			});
		this.tglBtnPause.addActionListener(new ActionListener()
			{

				@Override
				public void actionPerformed(ActionEvent event)
					{
					new Thread(new Runnable()
						{

							@Override
							public void run()
								{
								setControlEnabled(false);
								synchronized (listStationMeteoElements)
									{
									for(StationMeteoElement stationMeteoElement:listStationMeteoElements)
										{
										stationMeteoElement.setIsPaused(tglBtnPause.isSelected());
										}
									}
								setControlEnabled(true);
								}
						}).start();

					}
			});

		this.sliderDelayAltitude.addChangeListener(new ChangeListener()
			{

				@Override
				public void stateChanged(ChangeEvent event)
					{
					new Thread(new Runnable()
						{

							@Override
							public void run()
								{
								setControlEnabled(false);
								synchronized (listStationMeteoElements)
									{
									for(StationMeteoElement stationMeteoElement:listStationMeteoElements)
										{
										try
											{

											if (JFrameStationMeteo.getInstance().isLocal() == false)
												{
												stationMeteoElement.getAfficheurService().getMeteoServiceOptions().setAltitudeDT(sliderDelayAltitude.getValue());
												}
											else
												{
												stationMeteoElement.getMeteoService().getMeteoServiceOptions().setAltitudeDT(sliderDelayAltitude.getValue());
												}
											}
										catch (RemoteException e)
											{

											e.printStackTrace();
											}
										lblDelayAltitude.setText(String.valueOf(sliderDelayAltitude.getValue()));
										repaint();

										lblDelayAltitude.setForeground(Color.WHITE);

										}
									}
								setControlEnabled(true);
								}
						}).start();

					}
			});

		this.sliderDelayPression.addChangeListener(new ChangeListener()
			{

				@Override
				public void stateChanged(ChangeEvent event)
					{
					new Thread(new Runnable()
						{

							@Override
							public void run()
								{
								setControlEnabled(false);
								synchronized (listStationMeteoElements)
									{
									for(StationMeteoElement stationMeteoElement:listStationMeteoElements)
										{
										try
											{
											if (JFrameStationMeteo.getInstance().isLocal() == false)
												{

												stationMeteoElement.getAfficheurService().getMeteoServiceOptions().setPressionDT(sliderDelayPression.getValue());

												}
											else
												{
												stationMeteoElement.getMeteoService().getMeteoServiceOptions().setPressionDT(sliderDelayPression.getValue());
												}
											}
										catch (RemoteException e)
											{

											e.printStackTrace();
											}
										}
									lblDelayPression.setText(String.valueOf(sliderDelayPression.getValue()));
									repaint();
									lblDelayPression.setForeground(Color.WHITE);

									}
								setControlEnabled(true);
								}
						}).start();

					}
			});

		this.sliderDelayTemperature.addChangeListener(new ChangeListener()
			{

				@Override
				public void stateChanged(ChangeEvent event)
					{
					new Thread(new Runnable()
						{

							@Override
							public void run()
								{
								setControlEnabled(false);
								synchronized (listStationMeteoElements)
									{
									for(StationMeteoElement stationMeteoElement:listStationMeteoElements)
										{
										try
											{
											if (JFrameStationMeteo.getInstance().isLocal() == false)
												{

												stationMeteoElement.getAfficheurService().getMeteoServiceOptions().setTemperatureDT(sliderDelayTemperature.getValue());

												}
											else
												{
												stationMeteoElement.getMeteoService().getMeteoServiceOptions().setTemperatureDT(sliderDelayTemperature.getValue());
												}
											}
										catch (RemoteException e)
											{
											e.printStackTrace();
											}
										}
									lblDelayTemperature.setText(String.valueOf(sliderDelayTemperature.getValue()));
									repaint();
									lblDelayTemperature.setForeground(Color.WHITE);

									}
								setControlEnabled(true);
								}
						}).start();

					}
			});
		}

	private void setControlEnabled(boolean enabled)
		{
		this.btnStart.setEnabled(enabled);
		this.btnStop.setEnabled(enabled);
		this.tglBtnPause.setEnabled(enabled);
		this.sliderDelayAltitude.setEnabled(enabled);
		this.sliderDelayPression.setEnabled(enabled);
		this.sliderDelayTemperature.setEnabled(enabled);
		//this.controlEnabled = enabled;

		JFrameStationMeteo.getInstance().getPanelLeft().setEnabled(enabled);
		if (JFrameStationMeteo.getInstance().isLocal() == false)
			{
			JFrameStationMeteo.getInstance().getPanelCentral().getPanelMap().setEnabled(enabled);

			}
		controlEnabled = enabled;
		}

	private void geometry()
		{
		this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
		JPanel panelStartStop = new JPanel();
		panelStartStop.setLayout(new FlowLayout(FlowLayout.CENTER));

		this.btnStart = new JButton(new ImageIcon(ImageShop.IMAGE_START));
		this.btnStop = new JButton(new ImageIcon(ImageShop.IMAGE_STOP));
		this.tglBtnPause = new JToggleButton(new ImageIcon(ImageShop.IMAGE_PAUSE));

		panelStartStop.add(btnStart);
		panelStartStop.add(btnStop);
		panelStartStop.add(tglBtnPause);

		this.lblDelayAltitude = new JLabel(String.valueOf(DELAY_MIN));
		this.lblDelayPression = new JLabel(String.valueOf(DELAY_MIN));
		this.lblDelayTemperature = new JLabel(String.valueOf(DELAY_MIN));

		this.sliderDelayAltitude = new JSlider(DELAY_MIN, DELAY_MAX, DELAY_MIN);
		this.sliderDelayPression = new JSlider(DELAY_MIN, DELAY_MAX, DELAY_MIN);
		this.sliderDelayTemperature = new JSlider(DELAY_MIN, DELAY_MAX, DELAY_MIN);

		JPanel panelAltitude = new JPanel();
		panelAltitude.setLayout(new BorderLayout());
		panelAltitude.add(new JLabel("Delay altitude [ms]"), BorderLayout.WEST);
		panelAltitude.add(this.sliderDelayAltitude, BorderLayout.CENTER);
		panelAltitude.add(this.lblDelayAltitude, BorderLayout.EAST);

		JPanel panelPression = new JPanel();
		panelPression.setLayout(new BorderLayout());
		panelPression.add(new JLabel("Delay pression [ms]"), BorderLayout.WEST);
		panelPression.add(this.sliderDelayPression, BorderLayout.CENTER);
		panelPression.add(this.lblDelayPression, BorderLayout.EAST);

		JPanel panelTemperature = new JPanel();
		panelTemperature.setLayout(new BorderLayout());
		panelTemperature.add(new JLabel("Delay température [ms]"), BorderLayout.WEST);
		panelTemperature.add(this.sliderDelayTemperature, BorderLayout.CENTER);
		panelTemperature.add(this.lblDelayTemperature, BorderLayout.EAST);

		this.add(panelStartStop);
		this.add(panelAltitude);
		this.add(panelPression);
		this.add(panelTemperature);
		}

	/*------------------------------------------------------------------*\
	|*							Attributs Private						*|
	\*------------------------------------------------------------------*/

	//Input
	private List<StationMeteoElement> listStationMeteoElements;

	//Tools
	private JButton btnStart;
	private JButton btnStop;
	private JToggleButton tglBtnPause;

	private JLabel lblDelayAltitude;
	private JLabel lblDelayPression;
	private JLabel lblDelayTemperature;

	private JSlider sliderDelayAltitude;
	private JSlider sliderDelayPression;
	private JSlider sliderDelayTemperature;

	private int lastAltitudeDelay;
	private int lastPressionDelay;
	private int lastTemperatureDelay;

	private Timer updateTimer;
	private boolean controlEnabled = true;
	private static final int DELAY_MIN = 500;
	private static final int DELAY_MAX = 10000;

	private static final long DELAY_PULLING_SLIDER = 1000;

	}
